home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Atari Compendium
/
The Atari Compendium (Toad Computers) (1994).iso
/
files
/
umich
/
network
/
ka9q
/
ka9q_src.arc
/
FTPCLI.C
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-29
|
14KB
|
643 lines
/* FTP client (interactive user) code */
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "netuser.h"
#include "icmp.h"
#include "timer.h"
#include "tcp.h"
#include "iface.h"
#include "ax25.h"
#include "lapb.h"
#include "ftp.h"
#include "session.h"
#include "cmdparse.h"
extern struct session *current;
extern char nospace[];
extern char badhost[];
static char notsess[] = "Not an FTP session!\n";
static char cantwrite[] = "Can't write %s\n";
static char cantread[] = "Can't read %s\n";
int donothing(),doftpcd(),dolist(),doget(),dols(),dopass(),dopass2(),doput(),
dotype(),doabort(),domkdir(),dormdir();
struct cmds ftpabort[] = {
"abort", doabort, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0, "Only valid command is \"abort\"", NULLCHAR,
};
struct cmds ftpcmds[] = {
"", donothing, 0, NULLCHAR, NULLCHAR,
"cd", doftpcd, 2, "cd <directory>", NULLCHAR,
"dir", dolist, 0, NULLCHAR, NULLCHAR,
"list", dolist, 0, NULLCHAR, NULLCHAR,
"get", doget, 2, "get remotefile <localfile>", NULLCHAR,
"ls", dols, 0, NULLCHAR, NULLCHAR,
"mkdir", domkdir, 2, "mkdir <directory>", NULLCHAR,
"nlst", dols, 0, NULLCHAR, NULLCHAR,
"rmdir", dormdir, 2, "rmdir <directory>", NULLCHAR,
"pass", dopass, 1, "pass [<password>]", NULLCHAR,
"put", doput, 2, "put localfile <remotefile>", NULLCHAR,
"type", dotype, 0, NULLCHAR, NULLCHAR,
NULLCHAR, NULLFP, 0, NULLCHAR, NULLCHAR,
};
/* Handle top-level FTP command */
doftp(argc,argv)
int argc;
char *argv[];
{
int32 resolve();
int ftpparse();
char *inet_ntoa();
void ftpccr(),ftpccs();
struct session *s;
struct ftp *ftp,*ftp_create();
struct tcb *tcb;
struct socket lsocket,fsocket;
lsocket.address = ip_addr;
lsocket.port = lport++;
if((fsocket.address = resolve(argv[1])) == 0){
printf(badhost,argv[1]);
return 1;
}
if(argc < 3)
fsocket.port = FTP_PORT;
else
fsocket.port = atoi(argv[2]);
/* Allocate a session control block */
if((s = newsession()) == NULLSESSION){
printf("Too many sessions\n");
return 1;
}
current = s;
if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
strcpy(s->name,argv[1]);
s->type = FTP;
s->parse = ftpparse;
/* Allocate an FTP control block */
if((ftp = ftp_create(0)) == NULLFTP){
s->type = FREE;
printf(nospace);
return 1;
}
ftp->state = COMMAND_STATE;
s->cb.ftp = ftp; /* Downward link */
ftp->session = s; /* Upward link */
/* Now open the control connection */
tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
0,ftpccr,NULLVFP,ftpccs,0,(char *)ftp);
ftp->control = tcb;
go();
return 0;
}
/* Parse user FTP commands */
int
ftpparse(line,len)
char *line;
int16 len;
{
struct mbuf *bp;
if(current->cb.ftp->state == PASSCMD_STATE) {
(void)dopass2(line, len) ;
return ;
}
if(current->cb.ftp->state != COMMAND_STATE){
/* The only command allowed in data transfer state is ABORT */
if(cmdparse(ftpabort,line) == -1){
printf("Transfer in progress; only ABORT is acceptable\n");
}
fflush(stdout);
return;
}
/* Save it now because cmdparse modifies the original */
bp = qdata(line,len);
if(cmdparse(ftpcmds,line) == -1){
/* Send it direct */
if(bp != NULLBUF)
send_tcp(current->cb.ftp->control,bp);
else
printf(nospace);
} else {
free_p(bp);
}
fflush(stdout);
}
/* Handle null line to avoid trapping on first command in table */
static
int
donothing(argc,argv)
int argc;
char *argv[];
{
}
/* Translate 'cd' to 'cwd' for convenience */
static
int
doftpcd(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
}
/* Translate 'mkdir' to 'xmkd' for convenience */
static
int
domkdir(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
}
/* Translate 'rmdir' to 'xrmd' for convenience */
static
int
dormdir(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
}
/* Handle "type" command from user */
static
int
dotype(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
if(argc < 2){
switch(ftp->type){
case IMAGE_TYPE:
printf("Image\n");
break;
case ASCII_TYPE:
printf("Ascii\n");
break;
}
return 0;
}
switch(*argv[1]){
case 'i':
case 'b':
ftp->type = IMAGE_TYPE;
sndftpmsg(ftp,"TYPE I\r\n");
break;
case 'a':
ftp->type = ASCII_TYPE;
sndftpmsg(ftp,"TYPE A\r\n");
break;
case 'l':
ftp->type = IMAGE_TYPE;
sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
break;
default:
printf("Invalid type %s\n",argv[1]);
return 1;
}
return 0;
}
/* Start receive transfer. Syntax: get <remote name> [<local name>] */
static
doget(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
char *remotename,*localname;
register struct ftp *ftp;
char *mode;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
remotename = argv[1];
if(argc < 3)
localname = remotename;
else
localname = argv[2];
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(ftp->type == IMAGE_TYPE)
mode = binmode[WRITE_BINARY];
else
mode = "w";
if((ftp->fp = fopen(localname,mode)) == NULLFILE){
printf(cantwrite,localname);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer */
return sndftpmsg(ftp,"RETR %s\r\n",remotename);
}
/* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
static
dolist(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
register struct ftp *ftp;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(argc < 3){
ftp->fp = stdout;
} else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
printf(cantwrite,argv[2]);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer
* It's done this way to avoid confusing the 4.2 FTP server
* if there's no argument
*/
if(argc > 1)
return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
else
return sndftpmsg(ftp,"LIST\r\n","");
}
/* Abbreviated (name only) list of remote directory.
* Syntax: ls <remote directory/file> [<local name>]
*/
static
dols(argc,argv)
int argc;
char *argv[];
{
void ftpdr(),ftpcds();
register struct ftp *ftp;
ftp = current->cb.ftp;
if(ftp == NULLFTP){
printf(notsess);
return 1;
}
if(ftp->fp != NULLFILE && ftp->fp != stdout)
fclose(ftp->fp);
ftp->fp = NULLFILE;
if(argc < 3){
ftp->fp = stdout;
} else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
printf(cantwrite,argv[2]);
return 1;
}
ftp->state = RECEIVING_STATE;
ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
/* Generate the command to start the transfer */
if(argc > 1)
return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
else
return sndftpmsg(ftp,"NLST\r\n","");
}
/* Handle user "pass" command. Allow Blanking of password */
static
int
dopass(argc,argv)
int argc;
char *argv[];
{
register struct ftp *ftp;
ftp = current->cb.ftp;
if (argc > 1) /* Password printed in the clear - send it now */
return sndftpmsg(ftp,"PASS %s\r\n",argv[1]);
else {
ftp->state = PASSCMD_STATE ;
current->noecho = 1 ;
noecho() ;
printf("Enter user password: ") ;
fflush(stdout) ;
}
return 0;
}
/* Handle second half of user "pass" command: Blanked Password */
static
int
dopass2(line,len)
char *line;
int16 len;
{
register struct ftp *ftp;
ftp = current->cb.ftp;
ftp->state = COMMAND_STATE ;
current->noecho = 0 ;
echo() ;
/* Have unechoed password - send it */
line[len-1] = '\0' ;
return sndftpmsg(ftp,"PASS %s\r\n",line);
}
/* S